package com.kajespero.dao.commons.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.kajespero.dao.commons.PersistManager;
import com.kajespero.jdo.Criteria;
import com.kajespero.model.annotation.process.MappedValueProcess;
import com.kajespero.utils.PersistManagerJdoHelper;
import com.kajespero.vo.IdentifierVO;
import com.kajespero.vo.VO;

public class PersistManagerJDOImpl implements PersistManager{

	@Override
	public <T extends IdentifierVO<?>, Id extends Comparable<?>> T find(Class<T> clazz, Id identifier) {
		
		Long increment = (Long)identifier;
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("id", increment);
		return findBy(clazz, map);
	}

	@Override
	public <T extends IdentifierVO<Id>, Id extends Comparable<Id>> Collection<T> findAll(Class<T> clazz) {
		Criteria<T> criteria = new Criteria<T>(clazz);
		List<T> list = (List<T>) criteria.executeCriteria();
		List<T> returnList = new ArrayList<T>();
		for (T instance : list){
			returnList.add(MappedValueProcess.processPostLoad(instance));
		}
		return returnList;
	}

	@Override
	public <T extends IdentifierVO<?>> void saveOrUpdare(T instance) {
		PersistManagerJdoHelper.saveOrUpdate(MappedValueProcess.processPreSave(instance));
	}

	@Override
	public <T extends IdentifierVO<?>> void delete(T instance) {
		PersistManagerJdoHelper.delete(instance);
	}

	@Override
	public <Id extends Comparable<?>, T extends IdentifierVO<?>> void delete(
			Class<T> clazz, Id idendifier) {
		T instance = find(clazz, idendifier);
		delete(instance);
	}

	@Override
	public <T extends VO> Long lastIdentifier(Class<T> clazz) {
		Criteria<T> criteria = new Criteria<T>(clazz);
		Integer max = criteria.executeCriteria().size();
		return max.longValue();
	}

	@Override
	public <T extends IdentifierVO<?>> T findBy(Class<T> clazz, Map<String, Object> values) {
		Criteria<T> criteria = new Criteria<T>(clazz);
		for(String key : values.keySet()){
			criteria.addProperty(key, values.get(key));
		}
		List<T> results = (List<T>) criteria.executeCriteria();
		if(results != null && !results.isEmpty()){
			return MappedValueProcess.processPostLoad(results.get(0));
		}
		return null;
	}
}
